﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using System.IO.IsolatedStorage;

namespace MyGames
{
    static public class GamesManager
    {
        #region Declaration

        // Game content and difficult capicity
        static ContentManager _content = GameLoader.Content;
        static public float Difficult { get; private set; }

        // Game object
        static Player player;                          // Player
        static List<Enemy> enemies;                    // Enemies on the map
        static ParticleManager particles;              // Particle effects
        static PlayerSkillManager playerSkills;        // Player's skills projectiles and animations
        static EnemyProjectileManager enemyProjects;   // Enemies's projectiles
        static Map map;                                // Current map
        //static NPCManager _NPCs;                        // Cureent NPC

        // Activities var
        static float nextRespawnTime;
        static float respawnDelay = 20f;

        #endregion

        #region Initalize

        static public void InitGameManager()
        {
            // Normal difficult
            Difficult = 1f;

            // Map objects
            player = new Player();
            enemies = new List<Enemy>();
            particles = new ParticleManager();
            playerSkills = new PlayerSkillManager(player, enemies, particles);
            enemyProjects = new EnemyProjectileManager(player, particles);

            // Map and NPC
            map = new Map();
            //_NPCs = new NPCManager();

            // Post Initalize
            Enemy.Initalize(player, enemyProjects);
            EmuGamePad.InitEmuGamePad(playerSkills);
            //SkillScreen.InitSkillDialog(playerSkills);
            //InventoryScreen.InitInventory(player);
        }

        #endregion

        #region Helper methods

        static private void PauseGame()
        {
            TCOGame.GameState = GameState.Pause;
            TitleScreen.State = TitleScreen.TitleScreenState.Title;
            TitleScreen.UpdateMenuItem();
        }

        static private void InitEnemy()
        {
            enemies.Clear();

            int totalType = map.EnemyTypes.Count;
            if (totalType == 0) return;
            int minNumber = Camera.WorldRectangle.Width / 400;  // 1 monster / 200 px

            // Random monster
            for (int i = 0; i < minNumber; i++)
            {
                enemies.Add(new Enemy(map.EnemyTypes[RandomHelper.rand.Next(totalType)],
                    new Vector2(RandomHelper.rand.Next(900, Camera.WorldRectangle.Width - 100),
                                RandomHelper.rand.Next(330, 480))));
            }

            // Set some static monster and group
            int groupNum = Camera.WorldRectangle.Width / 3000;  // 1 group / 2000 px
            for (int i = 0; i < groupNum; i++)
            {
                for (int j = 0; j < totalType; j++)
                {
                    enemies.Add(new Enemy(map.EnemyTypes[j],
                        new Vector2(RandomHelper.rand.Next(900 + i * 2000, 1100 + i * 2000),
                                RandomHelper.rand.Next(330, 480))));
                }
            }
        }

        static private void UpdateRespawn(GameTime gameTime)
        {
            // Only respawn after a period of time and there are spaces for more enemies
            if (gameTime.TotalGameTime.TotalSeconds < nextRespawnTime ||
                enemies.Count >= Camera.WorldRectangle.Width / 100 ||
                map.EnemyTypes.Count == 0)
                return;

            // Random
            enemies.Add(new Enemy(map.EnemyTypes[RandomHelper.rand.Next(map.EnemyTypes.Count)],
                new Vector2(RandomHelper.rand.Next(900, Camera.WorldRectangle.Width - 100),
                RandomHelper.rand.Next(330, 480))));

            nextRespawnTime += respawnDelay;
        }

        static private void ChangeMap(Map.Waypoint wp)
        {
            particles.ClearAll();
            enemyProjects.ClearAll();

            map.UseThisWaypoint(player, wp);
            //_NPCs.LoadNPC(map.Location);
            InitEnemy();
        }

        #endregion

        #region Update and Draw

        static public void Update(GameTime gameTime)
        {
            // ------------------------- System tray -----------------------
            //if (SkillScreen.Activated || InventoryScreen.Activated)
            //{
            //    SkillScreen.Update(gameTime);
            //    InventoryScreen.Update(gameTime);
            //    return;
            //}

            if (EmuGamePad.IsEmuKeyTriggered(EmuButton.Pause)) PauseGame();
            //if (EmuGamePad.IsEmuKeyTriggered(EmuButton.ShowSkillDialog)) SkillScreen.Show();
            //if (EmuGamePad.IsEmuKeyTriggered(EmuButton.ShowInventory)) InventoryScreen.Show();

            // --------------------------- Player --------------------------
            player.Update(gameTime);
            playerSkills.Update(gameTime);

            // --------------------------- Enemies -------------------------
            UpdateRespawn(gameTime);
            enemyProjects.Update(gameTime);
            for (int i = 0; i < enemies.Count; i++)
            {
                // Remove dead enemies
                if (enemies[i].State == Enemy.EnemyState.Dead)
                {
                    // Experience, add here or in enemy class
                    enemies.RemoveAt(i);
                    continue;
                }

                // Being Attack
                if (enemies[i].IsCollideWith(player, true) && player.FinishAttacking &&
                    !enemies[i].Invicible && enemies[i].Health != 0)
                {
                    // Crit chance
                    float x = (float)RandomHelper.rand.NextDouble();
                    bool crit = x < player.CriticalChance;
                    particles.AddParticle(AttackType.Slash, enemies[i], crit);
                    enemies[i].GetDamage((int)(crit ? player.AttackPower * (2f + x + RandomHelper.rand.NextDouble()) : player.AttackPower));

                    //if (crit) AudioManager.PlayCue("DamageCritical");
                }

                // Main update
                enemies[i].Update(gameTime);
            }

            // --------------------------- Particles -----------------------
            particles.Update(gameTime);

            // ----------------------------- Maps --------------------------           
            // Map navigation
            foreach (Map.Waypoint wp in map.Waypoints)
            {
                if (wp.WPRectangle.Intersects(player.CollisionRectangle))
                {
                    if (EmuGamePad.IsEmuKeyTriggered(EmuButton.Attack))
                    {
                        ChangeMap(wp);
                        break;
                    }
                }
            }

            // Update
            map.Update(gameTime);
            //_NPCs.Update(gameTime);

        }

        static public void Draw(SpriteBatch spriteBatch)
        {
            // ------------------------- Interface -------------------------
            EmuGamePad.Draw(spriteBatch);
            //SkillScreen.Draw(spriteBatch);
            //InventoryScreen.Draw(spriteBatch);

            // --------------------------- Player --------------------------
            player.Draw(spriteBatch);
            playerSkills.Draw(spriteBatch);

            // -------------------------- Enemies --------------------------
            enemyProjects.Draw(spriteBatch);
            foreach (Enemy enemy in enemies)
                enemy.Draw(spriteBatch);

            // ------------------------- Particles -------------------------
            particles.Draw(spriteBatch);

            // ---------------------------- Maps ---------------------------
            map.Draw(spriteBatch);
            //_NPCs.Draw(spriteBatch);
        }

        #endregion

        #region Public methods

        static public void StartNewGame(float difficultCap)
        {
            // Cinematic
            // Implement some subclass to do: PlayCinematic("Intro");

            // In game
            Difficult = difficultCap;
            map.LoadBackground(Locations.PhodomHouse);
            //_NPCs.LoadNPC(Locations.PhodomHouse);
            InitEnemy();

            // Change state, shake baby!
            TCOGame.GameState = GameState.Playing;
        }

        static public void ContinueGame()
        {
        }

        static public void SaveGame()
        {
        }

        #endregion
    }

    struct SaveGameData
    {
        struct MapSaveData
        {
        }
    }

}
